package cn.glow.readingcloud.homepage.service.impl;


import cn.glow.readingcloud.account.feign.client.LikeSeeClient;
import cn.glow.readingcloud.book.feign.client.BookClient;
import cn.glow.readingcloud.common.constant.CategoryConstant;
import cn.glow.readingcloud.common.enums.BookSerialStatusEnum;
import cn.glow.readingcloud.common.pojo.Book;
import cn.glow.readingcloud.common.pojo.IndexBooklist;
import cn.glow.readingcloud.common.pojo.IndexBooklistItem;
import cn.glow.readingcloud.common.result.Result;
import cn.glow.readingcloud.common.result.ResultUtil;
import cn.glow.readingcloud.common.utils.CommonUtil;
import cn.glow.readingcloud.homepage.dao.IndexBooklistItemMapper;
import cn.glow.readingcloud.homepage.pojo.BookList;
import cn.glow.readingcloud.homepage.pojo.BookScore;
import cn.glow.readingcloud.homepage.service.BookCenterService;
import cn.glow.readingcloud.homepage.service.IndexBooklistItemService;
import cn.glow.readingcloud.homepage.service.IndexBooklistService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @Author Glow
 * @Date 2023-04-17 15:26:41
 * @Description 主页书单图书配置服务实现
 * @Version 1.0
 */
@Service
public class IndexBooklistItemServiceImpl extends ServiceImpl<IndexBooklistItemMapper, IndexBooklistItem> implements IndexBooklistItemService {


    private static final Logger LOGGER = LoggerFactory.getLogger(IndexBooklistItemServiceImpl.class);

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private IndexBooklistItemMapper indexBooklistItemMapper;
    @Autowired
    private IndexBooklistService indexBooklistService;
    @Autowired
    private BookCenterService bookCenterService;
    @Autowired
    private LikeSeeClient likeSeeClient;
    @Override
    public Result getBooklistPagingBooks(Integer booklistId, Integer page, Integer limit) {

        List<BookScore> bookScoreList = (List<BookScore>)redisTemplate.opsForHash().get("booklistitempage-id-"+booklistId,page.toString() + limit);
        if (CommonUtil.isEmpty(bookScoreList))
        {
            bookScoreList = new ArrayList<>();
            Page<IndexBooklistItem> pages = new Page<>(page,limit);
            LambdaQueryWrapper<IndexBooklistItem> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(IndexBooklistItem::getBooklistId,booklistId);
           List<IndexBooklistItem>  indexBooklistItemList = indexBooklistItemMapper.selectPage(pages,queryWrapper).getRecords();
            for(int i = 0 ; i < indexBooklistItemList.size(); i++)
            {
                String bookId = indexBooklistItemList.get(i).getBookId();
                BookScore score = this.getBookScore(bookId);
                if(score != null)
                {
                    bookScoreList.add(score);
                }
            }
            if(bookScoreList.size() > 0)
            {
                redisTemplate.opsForHash().put("booklistitempage-id-"+booklistId,page.toString() + limit,bookScoreList);
            }
        }
        return ResultUtil.success(bookScoreList);
    }
    public BookScore getBookScore(String bookId)
    {
        Book book = bookCenterService.getBookById(bookId);
        if(book == null)
        {
            LOGGER.warn("图书资源中心获取Book:{}失败！返回了空数据", bookId);
            return  null;
        }
        BookScore bookScore = new BookScore();
        BeanUtils.copyProperties(book,bookScore);
        bookScore.setLikeCount(0);
        bookScore.setCategoryName(CategoryConstant.categorys.get(book.getDicCategory()));
        bookScore.setSerialStatusName(BookSerialStatusEnum.values()[book.getDicSerialStatus() - 1].getName());
        return bookScore;
    }
    @Override
    public Result getBooklistExchange(Integer booklistId, Integer clientRandomNumber) {
        IndexBooklist indexBooklist = indexBooklistService.getIndexBooklistById(booklistId);
        if(indexBooklist == null)
        {
            return ResultUtil.notFound().buildMessage("找不到此书单哦！");

        }
        BookList bookList = indexBooklistService.getRandomIndexBooklistVO(indexBooklist,clientRandomNumber);
        return ResultUtil.success(bookList);
    }

    /**
     *
     * @param booklistId            书单ID
     * @param bookIds               图书IDs
     * @param showNumber            显示数量
     * @param clientRandomNumber    客户端当前随机编号
     * @param showLikeCount
     * @return
     */
    @Override
    public List<BookScore> getBooklistRandomBooks(Integer booklistId, String bookIds, Integer showNumber, Integer clientRandomNumber, Boolean showLikeCount) {
      String[] bookIdSplit = bookIds.split(",");
            if(showNumber > bookIdSplit.length)
            {
                // 若数据库中不够随机，直接返回顺序书单
                return this.getBooklistOrderBooks(booklistId, bookIds, showNumber, showLikeCount);
            }
        Set<String> clientBookIds = this.getClientBookIds(booklistId, clientRandomNumber);
        Random random = new Random();
        Set<String> randomBooks = new HashSet<>();
        while (randomBooks.size() < showNumber) {
            // 得到随机图书ID，并排重，排重客户端书单
            int randomIndex = random.nextInt(bookIdSplit.length);
            String bookId = bookIdSplit[randomIndex];
            if (!clientBookIds.contains(bookId) && !randomBooks.contains(bookId)) {
                randomBooks.add(bookId);
            }
        }

        String[] randomBookIdArray = {};
        randomBookIdArray = randomBooks.toArray(randomBookIdArray);
        return this.getBooklistBookVOByBookIdArray(randomBookIdArray, showNumber, showLikeCount);
    }
    /**
     * 获取书单VO
     * @param bookIdArray
     * @param showNumber
     * @param showLikeCount
     * @return
     */
    private List<BookScore> getBooklistBookVOByBookIdArray(String[] bookIdArray, Integer showNumber, Boolean showLikeCount){
        List<BookScore> vos = new ArrayList<>();
        for (int i = 0; i < bookIdArray.length; i++) {
            String bookId = bookIdArray[i];
            BookScore vo = this.getBookVO(bookId);
            if (vo != null) {
                // 获取喜欢数
                if (showLikeCount) {
                    Integer likeCount = this.likeSeeClient.getBookLikesCount(bookId).getData();
                    vo.setLikeCount(likeCount);
                }
                vos.add(vo);
            }

            // VOS到达榜单定制数量，不再获取了
            if (vos.size() == showNumber) {
                break;
            }
        }
        return vos;
    }

    /**
     * 获取榜单图书VO
     * @param bookId
     * @return
     */
    private BookScore getBookVO(String bookId){
        Book book = bookCenterService.getBookById(bookId);
        if (book == null) {
            LOGGER.warn("图书资源中心获取Book:{}失败！返回了空数据", bookId);
            return null;
        }
        BookScore vo = new BookScore();
        BeanUtils.copyProperties(book, vo);
        vo.setLikeCount(0);
        // 分类
        String categoryName = CategoryConstant.categorys.get(book.getDicCategory());
        vo.setCategoryName(categoryName);
        // 连载状态
        String serialStatusName = BookSerialStatusEnum.values()[book.getDicSerialStatus() - 1].getName();
        vo.setSerialStatusName(serialStatusName);
        return vo;
    }
    /**
     * 获取客户端书单Id集合
     * @param booklistId
     * @return
     */
    private Set<String> getClientBookIds(Integer booklistId, Integer clientRandomNumber){
        if (clientRandomNumber == null) {
            return new HashSet<>();
        }

        // 客户端当前显示的书单

        BookList booklist;
        List<BookScore> clientBooks = null;
        try {
            booklist = (BookList) redisTemplate.opsForHash().get("booklist-random-booklistId-"+booklistId, clientRandomNumber.toString());
            if (booklist != null) {
                clientBooks = booklist.getBooks();
            }
        } catch (Exception ex){
            LOGGER.error("Redis获取客户端书单失败了！booklistId:{},clientRandomNumber:{}", ex, booklistId, clientRandomNumber);
        }
        if (clientBooks == null) {
            clientBooks = new ArrayList<>();
        }
        return new HashSet(clientBooks);
    }

    /**
     *
     * @param booklistId            书单ID
     * @param bookIds               图书IDs
     * @param showNumber            显示数量
     * @param showLikeCount         显示喜欢数
     * @return
     */
    @Override
    public List<BookScore> getBooklistOrderBooks(Integer booklistId, String bookIds, Integer showNumber, Boolean showLikeCount) {
        String[] bookSpilt = bookIds.split(",");

        return this.getBooklistBookVOByBookIdArray(bookSpilt, showNumber, showLikeCount);
    }
}
